import React, { useState, useEffect } from 'react';

/**
 * useEffect Hook示例组件
 * 
 * 这个组件展示了React useEffect Hook的多种使用场景：
 * 1. 组件挂载时执行一次（空依赖数组）
 * 2. 每次渲染都执行（无依赖数组）
 * 3. 特定依赖项变化时执行（有依赖项的数组）
 * 4. 使用清理函数（return函数）
 * 5. 数据获取示例
 * 6. 订阅外部事件
 */
function UseEffectExample() {
  // 状态变量
  const [count, setCount] = useState(0);
  const [name, setName] = useState('');
  const [windowWidth, setWindowWidth] = useState(window.innerWidth);
  const [posts, setPosts] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [timer, setTimer] = useState(0);
  
  // 示例1: 仅在组件挂载时执行一次
  useEffect(() => {
    console.log('组件已挂载 - 这个效果只运行一次');
    
    // 可以在这里执行初始化操作，如：
    // - 初始化第三方库
    // - 加载初始数据
    // - 设置全局事件监听器
    
    document.title = '使用 useEffect 示例';
    
    // 可选的清理函数，在组件卸载时执行
    return () => {
      console.log('组件将卸载 - 清理一次性效果');
      document.title = 'React App'; // 恢复原始标题
    };
  }, []); // 空依赖数组表示这个effect只在组件挂载和卸载时运行
  
  // 示例2: 每次渲染后都执行
  useEffect(() => {
    console.log('组件已重新渲染，count =', count, 'name =', name);
    // 警告：如果在这里更新状态而没有条件检查，可能会导致无限循环
  }); // 没有依赖数组，每次渲染后都会执行
  
  // 示例3: 当特定依赖项变化时执行
  useEffect(() => {
    console.log('count 已更改为:', count);
    
    // 只有当count变化时才执行的逻辑
    if (count === 10) {
      alert('计数达到10!');
    }
  }, [count]); // 只有当count变化时才重新运行
  
  // 示例4: 使用清理函数处理窗口大小变化
  useEffect(() => {
    console.log('设置窗口大小监听器');
    
    // 定义处理窗口大小变化的函数
    const handleResize = () => {
      setWindowWidth(window.innerWidth);
    };
    
    // 添加事件监听器
    window.addEventListener('resize', handleResize);
    
    // 清理函数：移除事件监听器
    return () => {
      console.log('移除窗口大小监听器');
      window.removeEventListener('resize', handleResize);
    };
  }, []); // 空依赖数组表示只在挂载和卸载时运行
  
  // 示例5: 数据获取
  useEffect(() => {
    // 定义异步函数来获取数据
    const fetchPosts = async () => {
      setIsLoading(true);
      try {
        // 使用JSONPlaceholder API获取示例数据
        const response = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=5');
        const data = await response.json();
        setPosts(data);
      } catch (error) {
        console.error('获取数据时出错:', error);
      } finally {
        setIsLoading(false);
      }
    };
    
    // 调用异步函数
    fetchPosts();
    
    // 清理函数（可选）
    return () => {
      // 如果需要，可以在这里取消请求
      console.log('组件卸载，取消数据获取');
    };
  }, []); // 空依赖数组表示只在挂载时获取数据
  
  // 示例6: 使用定时器并清理
  useEffect(() => {
    console.log('启动定时器');
    
    // 设置一个每秒递增的定时器
    const intervalId = setInterval(() => {
      setTimer(prevTimer => prevTimer + 1);
    }, 1000);
    
    // 清理函数：清除定时器
    return () => {
      console.log('清除定时器');
      clearInterval(intervalId);
    };
  }, []); // 空依赖数组表示只在挂载和卸载时运行
  
  return (
    <div className="hook-example">
      <h2>useEffect Hook 示例</h2>
      
      {/* 示例1和2的交互部分 */}
      <section>
        <h3>基本状态更新</h3>
        <div>
          <button onClick={() => setCount(count + 1)}>
            增加计数: {count}
          </button>
          <input
            type="text"
            value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder="输入你的名字"
          />
          <p>名字: {name || '(空)'}</p>
        </div>
      </section>
      
      {/* 示例4的结果显示 */}
      <section>
        <h3>窗口大小监听 (useEffect 清理示例)</h3>
        <p>当前窗口宽度: {windowWidth}px</p>
        <p className="note">尝试调整浏览器窗口大小来查看效果</p>
      </section>
      
      {/* 示例5的结果显示 */}
      <section>
        <h3>数据获取示例</h3>
        {isLoading ? (
          <p>加载中...</p>
        ) : (
          <div>
            <h4>文章列表:</h4>
            <ul>
              {posts.map(post => (
                <li key={post.id}>{post.title}</li>
              ))}
            </ul>
          </div>
        )}
      </section>
      
      {/* 示例6的结果显示 */}
      <section>
        <h3>定时器示例 (自动清理)</h3>
        <p>计时器: {timer} 秒</p>
      </section>
      
      <div className="explanation">
            <h3>useEffect Hook 说明:</h3>
            <ul>
                <li><code>useEffect(() => &#123; /* 效果代码 */ &#125;, [依赖项])</code> - 执行副作用</li>
                <li>空依赖数组 <code>[]</code> - 仅在挂载和卸载时执行</li>
                <li>有依赖项的数组 <code>[a, b]</code> - 当依赖项变化时执行</li>
                <li>没有依赖数组 - 每次渲染后执行</li>
                <li>返回清理函数 <code>return () => &#123; /* 清理代码 */ &#125;</code> - 在effect重新运行前或组件卸载时执行</li>
                <li>适用场景: 数据获取、订阅、手动DOM修改、日志记录等</li>
            </ul>
        </div>

    </div>
  );
}

export default UseEffectExample;